/** * Copyright (C) 2010 Cloud.com, Inc. All rights reserved. * * This software is licensed under the GNU General Public License v3 or later. * * It is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ package com.cloud.utils.db; import java.lang.reflect.Field; import javax.persistence.AttributeOverride; import javax.persistence.Column; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Temporal; import javax.persistence.TemporalType; /** * The Java annotation are somewhat incomplete. This gives better information * about exactly what each field has. * */ public class Attribute { public enum Flag { Insertable(0x01), Updatable(0x02), Nullable(0x04), DaoGenerated(0x08), DbGenerated(0x10), Embedded(0x20), Id(0x40), Selectable(0x80), Time(0x100), Date(0x200), TimeStamp(0x400), SequenceGV(0x1000), TableGV(0x2000), AutoGV(0x4000), Created(0x10000), Removed(0x20000), DC(0x40000), CharDT(0x100000), StringDT(0x200000), IntegerDT(0x400000); int place; Flag(int place) { this.place = place; } public int place() { return place; } public boolean check(int value) { return (value & place) == place; } public int setTrue(int value) { return (value | place); } public int setFalse(int value) { return (value & ~place); } } protected String table; protected String columnName; protected Field field; protected int flags; protected Column column; public Attribute(Class<?> clazz, AttributeOverride[] overrides, Field field, String tableName, boolean isEmbedded, boolean isId) { this.field = field; flags = 0; table = tableName; setupColumnInfo(clazz, overrides, tableName, isEmbedded, isId); } public Attribute(String table, String columnName) { this.table = table; this.columnName = columnName; this.field = null; this.column = null; } protected void setupColumnInfo(Class<?> clazz, AttributeOverride[] overrides, String tableName, boolean isEmbedded, boolean isId) { flags = Flag.Selectable.setTrue(flags); GeneratedValue gv = field.getAnnotation(GeneratedValue.class); if (gv != null) { if (gv.strategy() == GenerationType.IDENTITY) { flags = Flag.DbGenerated.setTrue(flags); } else if (gv.strategy() == GenerationType.SEQUENCE) { assert (false) : "Sequence generation not supported."; flags = Flag.DaoGenerated.setTrue(flags); flags = Flag.Insertable.setTrue(flags); flags = Flag.SequenceGV.setTrue(flags); } else if (gv.strategy() == GenerationType.TABLE) { flags = Flag.DaoGenerated.setTrue(flags); flags = Flag.Insertable.setTrue(flags); flags = Flag.TableGV.setTrue(flags); } else if (gv.strategy() == GenerationType.AUTO) { assert (false) : "Auto generation not supported."; flags = Flag.DaoGenerated.setTrue(flags); flags = Flag.Insertable.setTrue(flags); flags = Flag.AutoGV.setTrue(flags); } } if (isEmbedded) { flags = Flag.Embedded.setTrue(flags); } if (isId) { flags = Flag.Id.setTrue(flags); } else { Id id = field.getAnnotation(Id.class); if (id != null) { flags = Flag.Id.setTrue(flags); } } column = field.getAnnotation(Column.class); if (gv == null) { if (column == null || (column.insertable() && column.table().length() == 0)) { flags = Flag.Insertable.setTrue(flags); } if (column == null || (column.updatable() && column.table().length() == 0)) { flags = Flag.Updatable.setTrue(flags); } if (column == null || column.nullable()) { flags = Flag.Nullable.setTrue(flags); } } Temporal temporal = field.getAnnotation(Temporal.class); if (temporal != null) { if (temporal.value() == TemporalType.DATE) { flags = Flag.Date.setTrue(flags); } else if (temporal.value() == TemporalType.TIME) { flags = Flag.Time.setTrue(flags); } else if (temporal.value() == TemporalType.TIMESTAMP) { flags = Flag.TimeStamp.setTrue(flags); } } if (column != null && column.table().length() > 0) { table = column.table(); } columnName = DbUtil.getColumnName(field, overrides); } public final boolean isInsertable() { return Flag.Insertable.check(flags); } public final boolean isUpdatable() { return Flag.Updatable.check(flags); } public final boolean isNullable() { return Flag.Nullable.check(flags); } public final boolean isId() { return Flag.Id.check(flags); } public final boolean isSelectable() { return Flag.Selectable.check(flags); } public final boolean is(Flag flag) { return flag.check(flags); } public final void setTrue(Flag flag) { flags = flag.setTrue(flags); } public final void setFalse(Flag flag) { flags = flag.setFalse(flags); } public Field getField() { return field; } public Object get(Object entity) { try { return field.get(entity); } catch (IllegalAccessException e) { assert (false) : "How did we get here?"; return null; } } @Override public int hashCode() { return columnName.hashCode(); } @Override public boolean equals(Object obj) { if (!(obj instanceof Attribute)) { return false; } Attribute that = (Attribute)obj; return columnName.equals(that.columnName) && table.equals(that.table); } }